using AutoMapper;
using B.S.XZYData.Api.Read.Application.Command.WorkOrder;
using B.S.XZYData.Api.Read.Dto.WorkOrder;
using B.S.XZYData.Domain.LJC;
using B.S.XZYData.ErrorCode;
using B.S.XZYData.Infrastructure.Interface;
using MediatR;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace B.S.XZYData.Api.Read.Application.Handler.WorkOrder
{
    /// <summary>
    /// 获取所有工单综合信息处理器（按工序展开）
    /// </summary>
    public class GetAllWorkOrderComprehensiveInfoHandler : IRequestHandler<GetAllWorkOrderComprehensiveInfoCommand, ApiResult<List<WorkOrderProcessComprehensiveDto>>>
    {
        private readonly IBaseRepository<WorkOrderModel> _workOrderRepo;
        private readonly IBaseRepository<WorkOrderProcessModel> _workOrderProcessRepo;
        private readonly IBaseRepository<WorkOrderAssignModel> _workOrderAssignRepo;
        private readonly IBaseRepository<PlanItemModel> _planItemRepo;
        private readonly IMapper _mapper;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="workOrderRepo">工单仓储</param>
        /// <param name="workOrderProcessRepo">工单工序仓储</param>
        /// <param name="workOrderAssignRepo">工单分派仓储</param>
        /// <param name="planItemRepo">计划项仓储</param>
        /// <param name="mapper">映射器</param>
        public GetAllWorkOrderComprehensiveInfoHandler(
            IBaseRepository<WorkOrderModel> workOrderRepo,
            IBaseRepository<WorkOrderProcessModel> workOrderProcessRepo,
            IBaseRepository<WorkOrderAssignModel> workOrderAssignRepo,
            IBaseRepository<PlanItemModel> planItemRepo,
            IMapper mapper)
        {
            _workOrderRepo = workOrderRepo;
            _workOrderProcessRepo = workOrderProcessRepo;
            _workOrderAssignRepo = workOrderAssignRepo;
            _planItemRepo = planItemRepo;
            _mapper = mapper;
        }

        /// <summary>
        /// 处理获取所有工单综合信息的请求
        /// </summary>
        /// <param name="request">请求命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>工单工序综合信息列表</returns>
        public Task<ApiResult<List<WorkOrderProcessComprehensiveDto>>> Handle(GetAllWorkOrderComprehensiveInfoCommand request, CancellationToken cancellationToken)
        {
            var res = new ApiResult<List<WorkOrderProcessComprehensiveDto>>();

            try
            {
                // 1. 构建工单查询条件
                var workOrderQuery = _workOrderRepo.GetAll();

                if (!string.IsNullOrWhiteSpace(request.WorkOrderCode))
                {
                    workOrderQuery = workOrderQuery.Where(x => x.Code.Contains(request.WorkOrderCode));
                }

                if (!string.IsNullOrWhiteSpace(request.ProductCode))
                {
                    workOrderQuery = workOrderQuery.Where(x => x.ProductCode != null && x.ProductCode.Contains(request.ProductCode));
                }

                if (!string.IsNullOrWhiteSpace(request.ProductName))
                {
                    workOrderQuery = workOrderQuery.Where(x => x.ProductName != null && x.ProductName.Contains(request.ProductName));
                }

                if (!string.IsNullOrWhiteSpace(request.WorkOrderStatus))
                {
                    workOrderQuery = workOrderQuery.Where(x => x.Status == request.WorkOrderStatus);
                }

                if (request.PlannedStartTimeStart.HasValue)
                {
                    workOrderQuery = workOrderQuery.Where(x => x.PlannedStartTime >= request.PlannedStartTimeStart);
                }

                if (request.PlannedStartTimeEnd.HasValue)
                {
                    workOrderQuery = workOrderQuery.Where(x => x.PlannedStartTime <= request.PlannedStartTimeEnd);
                }

                if (request.PlannedEndTimeStart.HasValue)
                {
                    workOrderQuery = workOrderQuery.Where(x => x.PlannedEndTime >= request.PlannedEndTimeStart);
                }

                if (request.PlannedEndTimeEnd.HasValue)
                {
                    workOrderQuery = workOrderQuery.Where(x => x.PlannedEndTime <= request.PlannedEndTimeEnd);
                }

                // 获取符合条件的工单列表
                var workOrders = workOrderQuery.ToList();
                var workOrderIds = workOrders.Select(w => w.Id).ToList();

                // 2. 构建工序查询条件
                var processQuery = _workOrderProcessRepo.GetAll()
                    .Where(x => workOrderIds.Contains(x.WorkOrderId));

                if (!string.IsNullOrWhiteSpace(request.ProcessCode))
                {
                    processQuery = processQuery.Where(x => x.ProcessCode.Contains(request.ProcessCode));
                }

                if (!string.IsNullOrWhiteSpace(request.ProcessName))
                {
                    processQuery = processQuery.Where(x => x.ProcessName.Contains(request.ProcessName));
                }

                if (!string.IsNullOrWhiteSpace(request.ProcessStatus))
                {
                    processQuery = processQuery.Where(x => x.Status == request.ProcessStatus);
                }

                // 获取符合条件的工序列表
                var processes = processQuery.ToList();
                
                // 在内存中进行多字段排序
                processes = processes
                    .OrderBy(x => x.WorkOrderId)
                    .ThenBy(x => x.Sequence)
                    .ToList();

                // 3. 获取所有相关的分派信息
                var processIds = processes.Select(p => p.Id).ToList();
                var assigns = _workOrderAssignRepo.GetAll()
                    .Where(x => processIds.Contains(x.WorkOrderProcessId))
                    .ToList();

                // 4. 获取计划明细信息
                var planItemIds = workOrders.Where(w => w.PlanItemId.HasValue)
                    .Select(w => w.PlanItemId.Value).Distinct().ToList();
                var planItems = _planItemRepo.GetAll()
                    .Where(x => planItemIds.Contains(x.Id))
                    .ToList();

                // 5. 构建综合信息列表
                var comprehensiveInfoList = new List<WorkOrderProcessComprehensiveDto>();

                foreach (var process in processes)
                {
                    var workOrder = workOrders.FirstOrDefault(w => w.Id == process.WorkOrderId);
                    if (workOrder == null) continue;

                    var planItem = planItems.FirstOrDefault(p => p.Id == workOrder.PlanItemId);
                    var processAssigns = assigns.Where(a => a.WorkOrderProcessId == process.Id).ToList();

                    var comprehensiveInfo = new WorkOrderProcessComprehensiveDto
                    {
                        WorkOrder = new WorkOrderBasicInfo
                        {
                            Id = workOrder.Id,
                            Code = workOrder.Code,
                            Status = workOrder.Status,
                            PlannedQuantity = workOrder.PlannedQuantity,
                            ActualQuantity = workOrder.ActualQuantity,
                            GoodQuantity = workOrder.GoodQuantity,
                            BadQuantity = workOrder.BadQuantity,
                            PlannedStartTime = workOrder.PlannedStartTime,
                            PlannedEndTime = workOrder.PlannedEndTime,
                            ActualStartTime = workOrder.ActualStartTime,
                            ActualEndTime = workOrder.ActualEndTime,
                            CreateTime = workOrder.CreateTime,
                            CreateBy = workOrder.CreateBy
                        },
                        Process = new ProcessDetailInfo
                        {
                            Id = process.Id,
                            Sequence = process.Sequence,
                            ProcessCode = process.ProcessCode,
                            ProcessName = process.ProcessName,
                            Status = process.Status,
                            PlannedQuantity = process.PlannedQuantity,
                            ReportedQuantity = process.ReportedQuantity,
                            GoodQuantity = process.GoodQuantity,
                            BadQuantity = process.BadQuantity,
                            Ratio = process.Ratio,
                            PlannedStartTime = process.PlannedStartTime,
                            PlannedEndTime = process.PlannedEndTime,
                            ActualStartTime = process.ActualStartTime,
                            ActualEndTime = process.ActualEndTime
                        },
                        Product = new ProductBasicInfo
                        {
                            ProductCode = workOrder.ProductCode,
                            ProductName = workOrder.ProductName,
                            Spec = workOrder.Spec,
                            Unit = workOrder.Unit
                        },
                        Plan = planItem != null ? new PlanBasicInfo
                        {
                            Id = planItem.Id,
                            PlanId = planItem.PlanId,
                            Quantity = planItem.Quantity,
                            DoneQuantity = planItem.DoneQuantity
                        } : null,
                        Assigns = processAssigns.Select(a => new AssignInfo
                        {
                            Id = a.Id,
                            EmployeeId = a.EmployeeId,
                            EmployeeName = a.EmployeeName,
                            Quantity = a.Quantity
                        }).ToList(),
                        Progress = CalculateProgress(workOrder, process, processAssigns)
                    };

                    comprehensiveInfoList.Add(comprehensiveInfo);
                }

                res.Data = comprehensiveInfoList;
                res.Code = ApiEnum.Success;
                res.Msg = $"获取工单综合信息成功，共{comprehensiveInfoList.Count}条工序记录";
            }
            catch (Exception ex)
            {
                res.Code = ApiEnum.Error;
                res.Msg = $"获取工单综合信息失败：{ex.Message}";
            }

            return Task.FromResult(res);
        }

        /// <summary>
        /// 计算进度统计
        /// </summary>
        private ProgressSummary CalculateProgress(WorkOrderModel workOrder, WorkOrderProcessModel process, List<WorkOrderAssignModel> assigns)
        {
            var progress = new ProgressSummary();

            // 计算工单完成百分比
            if (workOrder.PlannedQuantity.HasValue && workOrder.PlannedQuantity > 0)
            {
                var actualQty = workOrder.ActualQuantity ?? 0;
                progress.WorkOrderCompletionPercentage = Math.Round((decimal)actualQty / workOrder.PlannedQuantity.Value * 100, 2);
            }

            // 计算工序完成百分比
            if (process.PlannedQuantity.HasValue && process.PlannedQuantity > 0)
            {
                var reportedQty = process.ReportedQuantity ?? 0;
                progress.ProcessCompletionPercentage = Math.Round((decimal)reportedQty / process.PlannedQuantity.Value * 100, 2);
            }

            // 分派统计
            progress.TotalAssignQuantity = assigns.Sum(a => a.Quantity);
            progress.AssignedEmployeeCount = assigns.Count;

            // 分派状态判断
            if (assigns.Count == 0)
            {
                progress.AssignStatus = "未分派";
            }
            else if (process.PlannedQuantity.HasValue && progress.TotalAssignQuantity >= process.PlannedQuantity.Value)
            {
                progress.AssignStatus = "已满额分派";
            }
            else
            {
                progress.AssignStatus = "部分分派";
            }

            return progress;
        }
    }
}
